package me.yricky.kaguya.dsl

import me.yricky.kaguya.base.*
import me.yricky.kaguya.base.lu.AssignBlock
import me.yricky.kaguya.base.lu.CaseFrom
import me.yricky.kaguya.base.lu.SeqUnit

class SeqTrigScope{
    private val _cases = mutableListOf<SeqUnit.TrigCase>()
    internal fun cases() = _cases.toList()

    fun Signal.posEdge() {
        _cases.add(SeqUnit.PosEdge(this))
    }
    fun Signal.negEdge() {
        _cases.add(SeqUnit.NegEdge(this))
    }
}

class SeqLogicScope{
    private val _blocks = mutableListOf<AssignBlock>()
    internal fun blocks() = _blocks.toList()

    fun Reg.from(
        cases:List<CaseFrom>,
        default:Signal = ConstSignal(width,0)
    ){
        cases.forEach {
            assert(it.from.width == width)
        }
        _blocks.add(AssignBlock(this, cases, default))
    }

    fun Reg.from(
        vararg cases: CaseFrom,
        default:Signal = this
    ) = from(cases.toList(),default)

    infix fun Signal.to(that:Signal): CaseFrom {
        assert(width == 1)
        return CaseFrom(this,that)
    }
}

fun ModuleScope.seq(
    trig:SeqTrigScope.()->Unit,
    logic:SeqLogicScope.()->Unit
){
    val trigScope = SeqTrigScope().apply(trig)
    val logicScope = SeqLogicScope().apply(logic)
    _logicUnits.add(
        SeqUnit(
        trigScope.cases(),
        logicScope.blocks()
    )
    )
}